﻿using AbpVnext__Comon.iservice;
using AbpVnext_Module.Dto;
using AbpVnext_Module.Dto.User;
using FluentValidation;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
//using Microsoft.IdentityModel.JsonWebTokens;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Volo.Abp;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.ExceptionHandling;

namespace AbpVnext_Module.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    //[IgnoreAntiforgeryToken]  //忽略Token校验
    public class UserController : AbpController
    {

        public IUserService UserService { get; set; }

        public IConfiguration configuration { get; set; }


        public UserController()
        {

        }

        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="userDto"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> Login(UserDto userDto)
        {
            #region cookie 认证登录
            {
                //if (userDto.Name == "admin" && userDto.Passwd == "123456")
                //{
                //    //用户权限列表
                //    userDto.Role.Add("Product_Select");
                //    string role = JsonConvert.SerializeObject(userDto.Role);
                //    //创建声明集合
                //    Claim[] claims = new Claim[]
                //    {
                //        new Claim(ClaimTypes.Name, userDto.Name),
                //        new Claim("Passwd", userDto.Passwd),
                //        new Claim("UserRole",role)   //用户授权
                //    };
                //    //创建身份
                //    ClaimsIdentity claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
                //    AuthenticationProperties authenticationProperties = new AuthenticationProperties();
                //    //设置过期时间
                //    authenticationProperties.IsPersistent = true;
                //    authenticationProperties.ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(1);
                //    //实现登录
                //    await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity));
                //    //await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity), authenticationProperties);
                //    return Ok("登录成功");
                //}
                //else
                //{
                //    return Unauthorized("登录失败");
                //}
            }
            #endregion

            #region  jwt 认证登录
            {
                if (userDto.Name == "admin" && userDto.Passwd == "123456")
                {
                    userDto.Role.Add("Product_Select");
                    string role = JsonConvert.SerializeObject(userDto.Role);
                    Claim[] claims = new Claim[] {
                           new Claim (JwtRegisteredClaimNames.Name,userDto.Name),
                           //通过将jti设置为一个唯一的值（如UUID），JWT可以被用作一次性令牌。一旦令牌被使用或过期，它就不能再被接受，这减少了重放攻击的风险。
                           //在创建JWT时，应使用一种能够生成唯一值的算法（如UUID）来设置jti字段
                           //服务器应存储已使用的jti值，并在验证JWT时检查该值是否已被使用
                           //结合JWT的过期时间（exp字段）和唯一标识符，可以进一步增强安全性。即使攻击者截获了令牌，它也会在短时间内过期，无法被重放。
                           new Claim(JwtRegisteredClaimNames.Jti,Guid.NewGuid().ToString()),
                           new Claim("Passwd",userDto.Passwd),
                           new Claim("UserId",userDto.Id.ToString()),
                           //new Claim("UserRole",role)
                           new Claim("Role","Employee")
                     };
                    //string issuer = null, 签发者 。生产token系统
                    //string audience = null, 受用者 erp系统
                    //IEnumerable<Claim> claims = null,  登录信息
                    //DateTime? notBefore = null, 生成token时间
                    //DateTime? expires = null,  token过期时间
                    //SigningCredentials signingCredentials = null 签名凭证 【签名字符串】防止数据被篡改
                    //SecurityKey 密钥
                    //密钥：R2XMnd6TQdYRUmR0cCfL9fk651Fb3kDI
                    string? securityStr = configuration.GetSection("jwtSecurity").Value;
                    SecurityKey securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(securityStr ?? "R2XMnd6TQdYRUmR0cCfL9fk651Fb3kDI"));
                    //加密算法准备 非对称算法
                    //签名凭证
                    //SigningCredentials signingCredentials = new SigningCredentials(securityKey,SecurityAlgorithms.Sha256); //非对称算法
                    SigningCredentials signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256); //对称算法
                    JwtSecurityToken jwtSecurityToken = new JwtSecurityToken(
                                     issuer: "jwt",
                                     audience: "BasicModuleWebApiJWTAuthorization",
                                     claims: claims,
                                     notBefore: DateTime.Now,
                                     expires: DateTime.Now.AddMinutes(30.0),
                                     signingCredentials: signingCredentials);
                    //创建token 
                    JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
                    //生成token
                    string token = handler.WriteToken(jwtSecurityToken);
                    return Ok(token);
                }
                else
                {
                    return Unauthorized("登陆失败");
                }
            }
            #endregion
        }

        ///// <summary>
        ///// Validation 模块使用
        ///// </summary>
        ///// <param name="orderCreateDto"></param>
        ///// <returns></returns>
        //[HttpPost]
        //public string Post(OrderCreateDto orderCreateDto)
        //{
        //    var x = UserService.GetUser();
        //    return "测试是否成功";
        //}
    }
}
